// This file is part of Module Proxy.

// Module Proxy is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Module Proxy is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Module Proxy.  If not, see <https://www.gnu.org/licenses/>.


//         Copyright (C) 2021 - 2030  关中麦客  
//         All rights reserved
//
//         conf.rs
//         加载并解析配置文件
//
//         created by 关中麦客 1036038462@qq.com

use serde_derive;
use toml;
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path};
use once_cell::sync::OnceCell;
use serde_derive::Deserialize;

static CONFIG: OnceCell<Config> = OnceCell::new();    //全局缓存

/// 加载配置文件
pub fn load() -> Result<(), String>
{
    let home_str = super::home_path();
    let home_path = Path::new(home_str);
    let pathbuf = home_path.join("conf.toml");  //配置文件路径

    match File::open(pathbuf) {
        Ok(file) => 
        {
            match parse_file(file)       //解析文件
            {
                Ok(config) =>
                {
                    CONFIG.get_or_init(||{config});         //全局变量
                    return Ok(());
                }
                Err(err_string) =>
                {
                    return Err(err_string);
                }
            }
        },
        Err(e) => 
        {
            println!{"parse config file error: {}", e};
            return Err(e.to_string());
        }
    };   
}

/// 获得日志级别
pub fn log_level() -> &'static str
{
    if let Some(config) = CONFIG.get()
    {
        let level = &config.log.level;
        &level[..]
    }
    else
    {
        "info"  //默认info级别
    }
}

/// 获得侦听端口
pub fn server_port() -> u16
{
    if let Some(config) = CONFIG.get()
    {
        config.server.port
    }
    else
    {
        80  //默认80端口
    }    
}

/// 获得版本
pub fn version() -> &'static str
{
    if let Some(config) = CONFIG.get()
    {
        let version = &config.version;
        return version;
    }

    ""
}

/// 输出路径
pub fn out_path() -> &'static str
{
    if let Some(config) = CONFIG.get()
    {
        let out_path = &config.server.out_path;
        return out_path;
    }

    ""
}

/// cmd命令行
pub fn params() -> &'static str
{
    if let Some(config) = CONFIG.get()
    {
        let params = &config.transcoding.ffmpeg_params;
        return params;
    }

    ""
}

// --------------------------------------------------------------------------------------
//   私有函数
// --------------------------------------------------------------------------------------

#[derive(Deserialize)]
#[derive(Debug)]
struct Config 
{
    name: String,
    version: String,
    server: Server,
    transcoding: Transcoding,
    log: Log,
}

#[derive(Deserialize)]
#[derive(Debug)]
struct Server
{
    port: u16,
    out_path: String,
} 

#[derive(Deserialize)]
#[derive(Debug)]
struct Transcoding
{
    ffmpeg_params: String,
} 

#[derive(Deserialize)]
#[derive(Debug)]
struct Log
{
    level: String,
} 

/// 解析配置文件
///   成功返回Ok(()), 失败返回Err(e)
fn parse_file(mut file: File) -> Result<Config, String>
{
    //读配置文件
    let mut file_buf = String::new();
    if let Err(e) = file.read_to_string(&mut file_buf) 
    {
        //TODO 日志输出
        println!{"read config file error: {}", e};
        return Err(e.to_string());
    };

    //println!{"===================\n{}", &file_content};

    //解析配置
    match toml::from_str(&file_buf)
    {
        Ok(config) => 
        {
            // println!{"===================\n{:?}", &config};
            return Ok(config);  //成功返回
        },
        Err(e) =>
        {
            println!{"parse config file error: {}", e};
            return Err(e.to_string());
        }
    }
}